package com.zsqat.eshop.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.zsqat.common.constant.ProductConstant;
import com.zsqat.eshop.product.dao.AttrAttrgroupRelationDao;
import com.zsqat.eshop.product.dao.AttrGroupDao;
import com.zsqat.eshop.product.dao.CategoryDao;
import com.zsqat.eshop.product.entity.AttrAttrgroupRelationEntity;
import com.zsqat.eshop.product.entity.AttrGroupEntity;
import com.zsqat.eshop.product.entity.CategoryEntity;
import com.zsqat.eshop.product.service.CategoryService;
import com.zsqat.eshop.product.vo.AttrRespVo;
import com.zsqat.eshop.product.vo.AttrVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsqat.common.utils.PageUtils;
import com.zsqat.common.utils.Query;

import com.zsqat.eshop.product.dao.AttrDao;
import com.zsqat.eshop.product.entity.AttrEntity;
import com.zsqat.eshop.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
  @Resource
  public AttrAttrgroupRelationDao relationDao;

  @Resource
  private AttrGroupDao attrGroupDao;

  @Resource
  private CategoryDao categoryDao;

  @Resource
  private CategoryService categoryService;


  @Override
  public PageUtils queryPage(Map<String, Object> params) {
    IPage<AttrEntity> page = this.page(
        new Query<AttrEntity>().getPage(params),
        new QueryWrapper<AttrEntity>()
    );

    return new PageUtils(page);
  }

  @Override
  public PageUtils queryBaseAttrPage(Map<String, Object> params, Long categoryId, String attrType) {
    QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
    wrapper.eq("attr_type", "base".equalsIgnoreCase(attrType) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());

    if (categoryId != 0) {
      wrapper.eq("category_id", categoryId);
    }

    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
      // and() ===> Children and(Consumer<Param> consumer)
      wrapper.and(x -> {
        x.eq("attr_id", key).or().like("attr_name", key);
      });
    }

    IPage<AttrEntity> page = this.page(
        new Query<AttrEntity>().getPage(params),
        wrapper
    );


    List<AttrEntity> records = page.getRecords();
    List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
      AttrRespVo attrRespVo = new AttrRespVo();
      BeanUtils.copyProperties(attrEntity, attrRespVo);

      // 设置分组的名字
      if ("base".equalsIgnoreCase(attrType)) {
        AttrAttrgroupRelationEntity relationEntity =
            relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
        if (relationEntity != null && relationEntity.getAttrGroupId() != null) {
          AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
          attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
        }
      }

      // 设置分类名称
      CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCategoryId());
      if (categoryEntity != null) {
        attrRespVo.setCategoryName(categoryEntity.getName());
      }
      return attrRespVo;
    }).collect(Collectors.toList());
    PageUtils pageUtils = new PageUtils(page);
    pageUtils.setList(respVos);
    return pageUtils;
  }

  @Transactional(rollbackFor = Exception.class)
  @Override
  public void saveAttr(AttrVo attr) {
    AttrEntity attrEntity = new AttrEntity();
    BeanUtils.copyProperties(attr, attrEntity);

    // 1. 保存基本数据
    this.save(attrEntity);

    // 2. 保存关联关系
    // 判断类型，如果是基本属性就设置分组id
    if (attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId() != null) {
      AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
      relationEntity.setAttrGroupId(attr.getAttrGroupId());
      relationEntity.setAttrId(attrEntity.getAttrId());
      relationDao.insert(relationEntity);
    }
  }

  @Transactional(rollbackFor = Exception.class)
  @Override
  public void updateAttrById(AttrVo attr) {
    AttrEntity attrEntity = new AttrEntity();

    // 1. 更新基本数据
    BeanUtils.copyProperties(attr, attrEntity);
    this.updateById(attrEntity);
    if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
      // 1、修改分组关联
      AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
      relationEntity.setAttrGroupId(attr.getAttrGroupId());
      relationEntity.setAttrId(attr.getAttrId());

      Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>()
          .eq("attr_id", attr.getAttrId()));
      // 如果属性和属性分组关联表中没有分组信息(就是添加属性时没有选所属分组)，就添加上，以前如果有分组信息就更新
      if (count > 0) {
        relationDao.update(relationEntity,
            new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
      } else {
        relationDao.insert(relationEntity);
      }
    }
  }

  @Cacheable(value="attr", key="'attrInfo'+#root.args[0]")
  @Override
  public AttrRespVo getAttrInfo(Long attrId) {
    // 查询详细信息
    AttrEntity attrEntity = this.getById(attrId);
    // 查询分组信息
    AttrRespVo respVo = new AttrRespVo();
    BeanUtils.copyProperties(attrEntity, respVo);

    // 判断是否是基本类型
    if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
      // 1. 设置分组信息
      AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
      .eq("attr_id", attrId));

      if (relationEntity != null) {
        respVo.setAttrGroupId(relationEntity.getAttrGroupId());

        // 获取分组名称
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
        if (attrGroupEntity != null) {
          respVo.setGroupName(attrGroupEntity.getAttrGroupName());
        }
      }
    }
    // 2. 设置分类信息
    Long categoryId = attrEntity.getCategoryId();
    // 设置三级分类完整路径
    Long[] categoryPath = categoryService.findCategoryPath(categoryId);
    respVo.setCategoryPath(categoryPath);

    // 设置分类名
    CategoryEntity categoryEntity = categoryDao.selectById(categoryId);
    if (categoryEntity != null) {
      respVo.setCategoryName(categoryEntity.getName());
    }
    return respVo;
  }

  // 获取当前分组有被关联的所有属性
  @Override
  public List<AttrEntity> getRelationAttr(Long attrGroupId) {
    QueryWrapper<AttrAttrgroupRelationEntity> wrapper = new QueryWrapper<>();
    wrapper.eq("attr_group_id", attrGroupId);
    List<AttrAttrgroupRelationEntity> entities = relationDao.selectList(wrapper);

    List<Long> attrIds = entities.stream().map(relation -> relation.getAttrId()).collect(Collectors.toList());

    // 如果attrIds为空就直接返回一个null值出去
    if (attrIds == null || attrIds.size() == 0) {
      return null;
    }
    return this.baseMapper.selectBatchIds(attrIds);
  }

  // 获取当前分组没有被关联的所有属性
  @Override
  public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
    // 1、当前分组只能关联自己所属的分类里面的所有属性
    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
    // 获取当前分类的id
    Long catId = attrGroupEntity.getCategoryId();

    // 2、当前分组只能关联别的分组没有引用的属性
    // 2.1）、当前分类下的其它分组
    List<AttrGroupEntity> groupEntities = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>()
        .eq("category_id", catId));

    // 获取到所有的attrGroupId
    List<Long> collect = groupEntities.stream().map((item) -> {
      return item.getAttrGroupId();
    }).collect(Collectors.toList());


    // 2.2）、这些分组关联的属性
    List<AttrAttrgroupRelationEntity> groupId = relationDao.selectList
        (new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect));

    /*List<Long> attrIds = groupId.stream().map((item) -> {
      return item.getAttrId();
    }).collect(Collectors.toList());*/

    // 代码只有一行省略 1.return  2.{}  3.;
    List<Long> attrIds = groupId.stream()
        .map((x) -> x.getAttrId())
        .collect(Collectors.toList());

    //2.3）、从当前分类的所有属性移除这些属性
    QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>()
        .eq("category_id", catId).eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());

    if (attrIds != null && attrIds.size() > 0) {
      queryWrapper.notIn("attr_id", attrIds);
    }

    // 判断是否有参数进行模糊查询
    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
      queryWrapper.and((w) -> {
        w.eq("attr_id", key).or().like("attr_name", key);
      });
    }
    IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), queryWrapper);
    PageUtils pageUtils = new PageUtils(page);
    return pageUtils;
  }
}

/*
  可省略内容：

  1.(参数列表): 括号中的参数列表的数据类型，可以省略不写

  2.(参数列表): 括号中的参数如果只有一个，那么类型和()都可以省略

  3.(一些代码): 如果{}中的代码只有一行，无论是否有返回值，都可以省略({}、return、;)
*/








































